package com.wex.cookbook.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wex.cookbook.config.base.Result;
import com.wex.cookbook.dto.from.userInfo.LoginDto;
import com.wex.cookbook.dto.from.userInfo.RegisterDto;
import com.wex.cookbook.dto.from.userInfo.UpdateUserInfoDto;
import com.wex.cookbook.dto.to.userInfo.UserInfoDto;
import com.wex.cookbook.entity.Userinfo;
import com.wex.cookbook.exception.BizAssertUtils;
import com.wex.cookbook.mapper.UserinfoMapper;
import com.wex.cookbook.security.JwtTokenSecurityConfig;
import com.wex.cookbook.service.UserinfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wex.cookbook.utils.EncryptUtil;
import com.wex.cookbook.utils.JWTUtils;
import com.wex.cookbook.utils.RandomUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Objects;

import static com.wex.cookbook.utils.BaseRegexPatterns.*;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author wex
 * @since 2023-10-16
 */
@Service
public class UserinfoServiceImpl extends ServiceImpl<UserinfoMapper, Userinfo> implements UserinfoService {

    @Autowired
    private UserinfoMapper userinfoMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Override
    public Result<String> register(RegisterDto registerDto) {
        if(registerDto.getPhone() != null && !registerDto.getPhone().isEmpty()) {
            //判断手机号是否合法
            BizAssertUtils.isTrue(registerDto.getPhone().matches(PHONE_REGEX), "手机号格式不正确!");
        }
        if(registerDto.getEmail() != null && !registerDto.getEmail().isEmpty()) {
            //判断邮箱是否合法
            BizAssertUtils.isTrue(registerDto.getEmail().matches(EMAIL_REGEX), "邮箱格式不正确!");
        }
        //判断用户名是否存在
        LambdaQueryWrapper<Userinfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Userinfo::getUsername, registerDto.getUsername());
        List<Userinfo> userInfos = userinfoMapper.selectList(lambdaQueryWrapper);

        BizAssertUtils.isTrue(userInfos.size() == 0, "用户名已存在!");

        //判断手机号是否存在
        LambdaQueryWrapper<Userinfo> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper1.eq(Userinfo::getPhone, registerDto.getPhone());
        List<Userinfo> userInfos1 = userinfoMapper.selectList(lambdaQueryWrapper1);

        BizAssertUtils.isTrue(userInfos1.size() == 0, "手机号已存在!");

        //判断邮箱是否存在
        LambdaQueryWrapper<Userinfo> lambdaQueryWrapper2 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper2.eq(Userinfo::getEmail, registerDto.getEmail());
        List<Userinfo> userInfos2 = userinfoMapper.selectList(lambdaQueryWrapper2);
        BizAssertUtils.isTrue(userInfos2.size() == 0, "邮箱已存在!");

        final Userinfo userinfo = new Userinfo();
        userinfo.setUsername(registerDto.getUsername());
        final String pwd = registerDto.getPassword();
        final String passSalt = RandomUtil.randomNumber(5);
        final String encryptPass = EncryptUtil.encryptPassword(pwd, passSalt);
        userinfo.setPassword(encryptPass);
        userinfo.setPasswordSalt(passSalt);
        int insert = userinfoMapper.insert(userinfo);
        if(insert > 0){
            return Result.success("注册成功!", null);
        } else {
            return Result.fail("注册失败!", null);
        }
    }

    @Override
    public String login(LoginDto loginDto) {
        //从redis中读取验证码信息
        String code = redisTemplate.opsForValue().get("_code");
        //判断验证码是否正确
        BizAssertUtils.isTrue(Objects.equals(code, loginDto.getCode()), "验证码不正确!");

        Userinfo userinfo = null;
        //判断用户使用的是用户名还是手机号还是邮箱登录
        if(loginDto.getAccount().matches(PHONE_REGEX)) {
            //手机号登录
            LambdaQueryWrapper<Userinfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(Userinfo::getPhone, loginDto.getAccount());
            userinfo = userinfoMapper.selectOne(lambdaQueryWrapper);
            BizAssertUtils.isFalse(userinfo == null , "手机号不存在!");
        } else if(loginDto.getAccount().matches(EMAIL_REGEX)) {
            //邮箱登录
            LambdaQueryWrapper<Userinfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(Userinfo::getEmail, loginDto.getAccount());
            userinfo = userinfoMapper.selectOne(lambdaQueryWrapper);
            BizAssertUtils.isFalse(userinfo == null , "邮箱不存在!");
        } else {
            //用户名登录
            LambdaQueryWrapper<Userinfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(Userinfo::getUsername, loginDto.getAccount());
            userinfo = userinfoMapper.selectOne(lambdaQueryWrapper);
            BizAssertUtils.isFalse(userinfo == null , "用户名不存在!");
        }


        //判断密码是否正确
        final String pwd =EncryptUtil.encryptPassword(loginDto.getPassword(), userinfo.getPasswordSalt());
        BizAssertUtils.isTrue(Objects.equals(pwd, userinfo.getPassword()), "密码不正确!");

        //设置用户状态为在线
        userinfo.setStatus(1);

        //更新用户信息
        userinfoMapper.updateById(userinfo);

        //添加到在线账号清单
        JwtTokenSecurityConfig.accountOnlineList.add(userinfo.getUsername());

        //生成token
        return JWTUtils.createToken(JSONUtil.toJsonStr(userinfo));
    }

    @Override
    public Result<String> updateUserInfoPassword(UpdateUserInfoDto updateUserInfoDto) {

        //判断密码是否符合格式
        BizAssertUtils.isTrue(updateUserInfoDto.getNewPassword().matches(PASSWORD_REGEX), "密码格式不正确!");

        //判断新密码和确认密码是否一致
        BizAssertUtils.isTrue(Objects.equals(updateUserInfoDto.getNewPassword(), updateUserInfoDto.getConfirmPassword()), "新密码和确认密码不一致!");
        //判断原密码是否正确
        LambdaQueryWrapper<Userinfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Userinfo::getUsername, updateUserInfoDto.getUsername());
        Userinfo userinfo = userinfoMapper.selectOne(lambdaQueryWrapper);
        BizAssertUtils.isTrue(Objects.equals(EncryptUtil.encryptPassword(updateUserInfoDto.getPassword(), userinfo.getPasswordSalt()), userinfo.getPassword()), "原密码不正确!");

        //修改密码
        final String encryptPass = EncryptUtil.encryptPassword(updateUserInfoDto.getNewPassword(), userinfo.getPasswordSalt());
        userinfo.setPassword(encryptPass);
        int i = userinfoMapper.updateById(userinfo);
        if (i > 0) {
            return Result.success("修改密码成功!", null);
        } else {
            return Result.fail("修改密码失败!", null);
        }
    }

    @Override
    public Result<String> updateUserInfoPhone(UpdateUserInfoDto updateUserInfoDto) {
        //判断手机号是否合法
        BizAssertUtils.isTrue(updateUserInfoDto.getPhone().matches(PHONE_REGEX), "手机号格式不正确!");

        //判断手机号是否存在
        LambdaQueryWrapper<Userinfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Userinfo::getPhone, updateUserInfoDto.getPhone());
        List<Userinfo> userInfos = userinfoMapper.selectList(lambdaQueryWrapper);
        if(userInfos.size() > 0) {
            return Result.fail("手机号已被使用!", null);
        }

        //判断验证码是否正确


        //修改手机号
        LambdaQueryWrapper<Userinfo> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper1.eq(Userinfo::getUsername, updateUserInfoDto.getUsername());
        Userinfo userinfo = userinfoMapper.selectOne(lambdaQueryWrapper1);

        userinfo.setPhone(updateUserInfoDto.getPhone());

        int i = userinfoMapper.updateById(userinfo);
        if(i > 0) {
            return Result.success("修改手机号成功!", null);
        } else {
            return Result.fail("修改手机号失败!", null);
        }
    }

    @Override
    public Result<String> updateUserInfoEmail(UpdateUserInfoDto updateUserInfoDto) {
        //判断邮箱是否合法
        BizAssertUtils.isTrue(updateUserInfoDto.getEmail().matches(EMAIL_REGEX), "邮箱格式不正确!");

        //判断邮箱是否存在
        LambdaQueryWrapper<Userinfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Userinfo::getEmail, updateUserInfoDto.getEmail());
        List<Userinfo> userInfos = userinfoMapper.selectList(lambdaQueryWrapper);
        if(userInfos.size() > 0) {
            return Result.fail("邮箱已被使用!", null);
        }

        //判断验证码是否正确

        //修改邮箱
        LambdaQueryWrapper<Userinfo> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper1.eq(Userinfo::getUsername, updateUserInfoDto.getUsername());
        Userinfo userinfo = userinfoMapper.selectOne(lambdaQueryWrapper1);

        userinfo.setEmail(updateUserInfoDto.getEmail());
        int i = userinfoMapper.updateById(userinfo);
        if(i > 0) {
            return Result.success("修改邮箱成功!", null);
        } else {
            return Result.fail("修改邮箱失败!", null);
        }
    }

    @Override
    public Result<UserInfoDto> getUserInfo(String username) {
        LambdaQueryWrapper<Userinfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Userinfo::getUsername, username);
        Userinfo userinfo = userinfoMapper.selectOne(lambdaQueryWrapper);
        if(userinfo != null) {
            UserInfoDto userInfoDto = new UserInfoDto();
            BeanUtils.copyProperties(userinfo, userInfoDto);
            return Result.success("获取用户信息成功!", userInfoDto);
        } else {
            return Result.fail("获取用户信息失败!", null);
        }
    }

    @Override
    public Result<String> deleteUserInfo(String username) {
        //逻辑删除
        LambdaQueryWrapper<Userinfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Userinfo::getUsername, username);
        Userinfo userinfo = userinfoMapper.selectOne(lambdaQueryWrapper);
        userinfo.setDeleted(1);
        int i = userinfoMapper.updateById(userinfo);
        //从在线账号清单中移除
        JwtTokenSecurityConfig.accountOnlineList.remove(username);
        if(i > 0) {
            return Result.success("注销成功!", null);
        } else {
            return Result.fail("注销失败!", null);
        }
    }

    @Override
    public Result<String> updateUserInfo(UpdateUserInfoDto updateUserInfoDto) {
        LambdaQueryWrapper<Userinfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Userinfo::getUsername, updateUserInfoDto.getUsername());
        Userinfo userinfo = userinfoMapper.selectOne(lambdaQueryWrapper);

        userinfo.setRealName(updateUserInfoDto.getRealName() == null? userinfo.getRealName() : updateUserInfoDto.getRealName());
        userinfo.setAvatar(updateUserInfoDto.getAvatar() == null? userinfo.getAvatar() : updateUserInfoDto.getAvatar());
        userinfo.setSex(updateUserInfoDto.getSex() == null? userinfo.getSex() : updateUserInfoDto.getSex());

        int i = userinfoMapper.updateById(userinfo);
        if(i > 0) {
            return Result.success("修改用户信息成功!", null);
        } else {
            return Result.fail("修改用户信息失败!", null);
        }
    }

}
